package main

import (
	"bytes"
	"compress/gzip"
	"encoding/json"
	"flag"
	"fmt"
	"github.com/RoaringBitmap/roaring/roaring64"
	"go.manyji.com/lib/util/convert"
	"io"
	"os"
	"strings"
)

var (
	str            = flag.String("s", "", "需要编码或者解码的字串")
	decodeOrEncode = flag.Bool("e", true, "编码或者解码（true：解码，false：编码）")
	ty             = flag.Int("t", 1, "编解码字符串类型(1:base64,2:[]byte)")
)

// 格式：12|23|26126|
func aggIds2BitMap(agIds string) string {

	var s []uint64
	for _, v := range strings.Split(agIds, "|") {

		s = append(s, uint64(convert.Atoi(v)))
	}

	ss, _ := roaring64.BitmapOf(s...).ToBase64()

	return ss
}

// 格式：AQAAAAAAAAAAAAAAOjAAAAEAAAAAAAIAEAAAAAEAAgADAA==
func bitMap2aggIds(str string) interface{} {

	var (
		ba = roaring64.New()
		s  []string
	)

	_, _ = ba.FromBase64(str)
	for _, v := range ba.ToArray() {
		s = append(s, fmt.Sprintf("%v", v))
	}

	return map[string]interface{}{
		"total": len(s),
		"list":  strings.Join(s, "|"),
	}
}

func compressData(input []byte) ([]byte, error) {
	var compressedBuffer bytes.Buffer
	gzipWriter := gzip.NewWriter(&compressedBuffer)
	_, err := gzipWriter.Write(input)
	if err != nil {
		return nil, err
	}
	gzipWriter.Close()
	return compressedBuffer.Bytes(), nil
}

func decompressData(compressedData []byte) ([]byte, error) {
	gzipReader, err := gzip.NewReader(bytes.NewReader(compressedData))
	if err != nil {
		return nil, err
	}
	defer gzipReader.Close()
	decompressedData, err := io.ReadAll(gzipReader)
	if err != nil {
		return nil, err
	}
	return decompressedData, nil
}

func decodeData(byteData []byte) (*roaring64.Bitmap, error) {

	b1, err := decompressData(byteData)
	if err != nil {
		return nil, err
	}

	b := roaring64.NewBitmap()
	_, _ = b.ReadFrom(bytes.NewReader(b1))
	return b, nil
}

func encodeData(ba *roaring64.Bitmap) ([]byte, error) {

	b, err := ba.ToBytes()
	if err != nil {
		return nil, err
	}

	return compressData(b)
}

func bitMapBytes2aggIds(str string) interface{} {

	var (
		s []string
	)

	ba, err := decodeData([]byte(str))
	if err != nil {
		fmt.Println("解析错误:", err)
		os.Exit(-1)
	}

	for _, v := range ba.ToArray() {
		s = append(s, fmt.Sprintf("%v", v))
	}

	return map[string]interface{}{
		"total": len(s),
		"list":  strings.Join(s, "|"),
	}
}

func aggIds2BitMapBytes(agIds string) interface{} {

	var s []uint64
	for _, v := range strings.Split(agIds, "|") {

		s = append(s, uint64(convert.Atoi(v)))
	}

	ba := roaring64.BitmapOf(s...)

	b, err := encodeData(ba)
	if err != nil {
		fmt.Println("出错啦，", err)
		os.Exit(-1)
	}
	return string(b)
}

/*
1. ./bitmap -s="92" -e=false
*/
func main() {

	flag.Parse()
	if *str == "" {
		flag.Usage()
		return
	}
	if *decodeOrEncode {
		if *ty == 1 {
			b, _ := json.MarshalIndent(bitMap2aggIds(*str), "", " ")
			fmt.Println(string(b))
		}
		if *ty == 2 {
			b, _ := json.MarshalIndent(bitMapBytes2aggIds(*str), "", " ")
			fmt.Println(string(b))
		}
	} else {
		if *ty == 1 {
			b, _ := json.MarshalIndent(aggIds2BitMap(*str), "", " ")
			fmt.Println(string(b))
		}
		if *ty == 2 {
			b, _ := json.MarshalIndent(aggIds2BitMapBytes(*str), "", " ")
			fmt.Println(string(b))

		}
	}

}
